package com.zwh.tool.utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

//文件工具类
public class FileUtils {

    /**
     * 列出给定目录中的全部文件的路径，包括给定目录下面的所有子目录。
     *
     * @param file
     */
    public static void list(List<File> files, File file) {
        if (file.isDirectory()) {
            //File[] listFiles() ：列出所有文件对象（指的是存放数据的容器）
            File[] fs = file.listFiles();
            if (fs != null) {
                for (File f : fs) {
                    list(files, f);
                }
            }
        } else {
            files.add(file);
        }
    }

    /**
     * 打印出所传文件对象的绝对路径、真实路径和相对路径
     *
     * @param file
     * @throws IOException
     */
    public static void printPaths(File file) throws IOException {
        // String getAbsolutePath()：获取提供的抽象路径的绝对路径。
        // 如果使用绝对路径名创建File对象，则直接返回路径名pathname。
        // 如果提供的抽象路径名是空的抽象路径名，则返回当前用户目录的路径名字符串，该路径名由系统属性user.dir命名。
        // 否则，此路径名将以系统相关的方式解析。
        // 在UNIX系统上，通过将相对路径名解析为当前用户目录，使其成为绝对路径名。
        // 在Windows系统上，通过将路径名解析为路径名所指定的驱动器的当前目录（如果有），使相对路径名成为绝对路径名; 如果没有，则针对当前用户目录解析。
        System.out.println("绝对路径(Absolute Path): " + file.getAbsolutePath());
        // String getCanonicalPath()：获取真实路径。返回绝对唯一的标准规范路径名。
        // 此方法首先将此路径名转换为绝对形式，就像调用getAbsolutePath方法一样，然后以系统相关的方式将其映射到其唯一路径上。
        // 简单来说就是如果路径中包含“.”或“..”等当前路径及上层路径表示法，则会从路径名中删除“.”和“..”使用真实路径代替。
        // 另外比较重点的是，它还会解析软链接（在UNIX平台上）以及驱动器号（在Microsoft Windows平台上），将它们转换为标准实际路径。
        System.out.println("真实路径(Canonical Path): " + file.getCanonicalPath());
        // String getPath()：获取相对路径(relative path)。
        // 若是使用抽象路径，则传了什么pathname，就获取什么pathname。如果URI用作参数，则它将删除协议并返回文件名。
        // 所谓相对路径,就是找一个参照物,然后让该文件的路径相对于它而存在。比如如果在main方法中，相对的就是本项目路径。(如果是在junit中,则指的是模块位置)
        System.out.println("相对路径(Path): " + file.getPath());
        System.out.println("----------------------------------------------------------------");
    }

    /**
     * 保存文件
     *
     * @param content
     * @param filePath
     */
    public static void saveFile(Object content, String filePath) {
        //查询有无该文件，没有就保存
        File file = new File(filePath);
        if (file.exists()) {
            return;
        }
        Writer writer = null;
        try {
            writer = new FileWriter(file);
            writer.write(JsonUtil.toJson(content));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                writer.flush();
                writer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 移动文件
     *
     * @param file                 文件
     * @param destinationFloderUrl 移动路径
     * @return
     */
    public static boolean moveFile(File file, String destinationFloderUrl) {
        File destFloder = new File(destinationFloderUrl);
        //检查目标路径是否合法
        if (destFloder.exists()) {
            if (destFloder.isFile()) {
                System.out.println("目标路径是个文件，请检查目标路径！");
                return false;
            }
        } else {
            if (!destFloder.mkdirs()) {
                System.out.println("目标文件夹不存在，创建失败！");
                return false;
            }
        }
        //检查源文件是否合法
        if (file.isFile() && file.exists()) {
            String destinationFile = destinationFloderUrl + "/" + file.getName();
            if (!file.renameTo(new File(destinationFile))) {
                System.out.println("移动文件失败！");
                return false;
            }
        } else {
            System.out.println("要备份的文件路径不正确，移动失败！");
            return false;
        }
        System.out.println("已成功移动文件" + file.getName() + "到" + destinationFloderUrl);
        return true;
    }

    /**
     * 获取此demo项目的输出路径
     *
     * @param fileName 文件名称
     * @return
     */
    public static String outputPath(String fileName) {
        return "file/" + fileName;
    }

    /**
     * Linux系统，使用touch命令创建文件
     * @param filePath 文件路径
     * @param auth 权限 755
     */
    public static void touchCreateFile(String filePath,String auth) {
        // 文件路径
//        String filePath = "/path/to/your/file.txt";

        // 使用touch命令创建文件
        ProcessBuilder createFileBuilder = new ProcessBuilder("touch", filePath);
        try {
            Process createFileProcess = createFileBuilder.start();
            createFileProcess.waitFor();

            // 设置文件权限，例如755
            ProcessBuilder changePermissionBuilder = new ProcessBuilder("chmod", auth, filePath);
            Process changePermissionProcess = changePermissionBuilder.start();
            changePermissionProcess.waitFor();

            System.out.println("文件创建并授权成功！");
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            System.out.println("执行命令时出错：" + e.getMessage());
        }
    }

    /**
     * Linux系统,设置777权限
     * @param file 文件路径
     */
    public static void chmod777(File file) throws IllegalStateException {
        //设置权限
        Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
        perms.add(PosixFilePermission.OWNER_READ); //设置所有者的读取权限
        perms.add(PosixFilePermission.OWNER_WRITE); //设置所有者的写权限
        perms.add(PosixFilePermission.OWNER_EXECUTE); //设置所有者的执行权限
        perms.add(PosixFilePermission.GROUP_READ); //设置组的读取权限
        perms.add(PosixFilePermission.GROUP_WRITE); //设置组的写权限
        perms.add(PosixFilePermission.GROUP_EXECUTE); //设置组的执行权限
        perms.add(PosixFilePermission.OTHERS_READ); //设置其他的读取权限
        perms.add(PosixFilePermission.OTHERS_WRITE); //设置其他的写权限
        perms.add(PosixFilePermission.OTHERS_EXECUTE); //设置其他的执行权限
        try {
            //设置文件和文件夹的权限
            Path pathParent = Paths.get(file.getParentFile().getAbsolutePath());
            Path pathDest = Paths.get(file.getAbsolutePath());
            Files.setPosixFilePermissions(pathParent, perms);   //修改文件夹路径的权限
            Files.setPosixFilePermissions(pathDest, perms);  //修改图片文件的权限
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
